bitkeeper revision 1.1159.1.131 (413ddc610qK3tZi2_2-e23mt5avoNA)
authorcl349@freefall.cl.cam.ac.uk <cl349@freefall.cl.cam.ac.uk>
Tue, 7 Sep 2004 16:05:53 +0000 (16:05 +0000)
committercl349@freefall.cl.cam.ac.uk <cl349@freefall.cl.cam.ac.uk>
Tue, 7 Sep 2004 16:05:53 +0000 (16:05 +0000)
Load (Net)BSD symbol table from ELF image if requested.

netbsd-2.0-xen-sparse/sys/arch/xen/i386/locore.S
netbsd-2.0-xen-sparse/sys/arch/xen/i386/machdep.c
tools/libxc/xc_linux_build.c

index 45af67272f5dca2dc0bf21ba0ce8fb430d8294c1..6a1a3e7bd8ab295d42d9f5b19a090969afed6c1a 100644 (file)
  * Xen guest identifier and loader selection
  */
 .section __xen_guest
-       .asciz "GUEST_OS=netbsd,GUEST_VER=2.0,XEN_VER=2.0,LOADER=generic"
+       .ascii  "GUEST_OS=netbsd,GUEST_VER=2.0,XEN_VER=2.0"
+       .ascii  ",LOADER=generic"
+#if (NKSYMS || defined(DDB) || defined(LKM)) && !defined(SYMTAB_SPACE)
+       .ascii  ",BSD_SYMTAB"
+#endif
+       .byte   0
 
 
 /*
        .data
 
        .globl  _C_LABEL(cpu)
-       .globl  _C_LABEL(esym),_C_LABEL(boothowto)
+       .globl  _C_LABEL(boothowto)
        .globl  _C_LABEL(bootinfo),_C_LABEL(atdevbase)
 #ifdef COMPAT_OLDBOOT
        .globl  _C_LABEL(bootdev)
@@ -228,7 +233,6 @@ _C_LABEL(lapic_tpr):
 
 _C_LABEL(cpu):         .long   0       # are we 386, 386sx, or 486,
                                        #   or Pentium, or..
-_C_LABEL(esym):                .long   0       # ptr to end of syms
 _C_LABEL(atdevbase):   .long   0       # location of start of iomem in virtual
 _C_LABEL(proc0paddr):  .long   0
 _C_LABEL(PTDpaddr):    .long   0       # paddr of PTD, for libkvm
@@ -254,11 +258,6 @@ tmpstk:
 #define        _RELOC(x)       ((x))
 #define        RELOC(x)        _RELOC(_C_LABEL(x))
 
-/* XXX assym.h */
-#define MOD_START   48
-#define MOD_LEN     56
-/* XXX assym.h */
-
        .text
        .globl  _C_LABEL(kernel_text)
        .set    _C_LABEL(kernel_text),KERNTEXTOFF
@@ -271,13 +270,6 @@ start:
 
        movl    %esi,%ebx               # save start_info pointer
 
-#if (NKSYMS || defined(DDB) || defined(LKM)) && !defined(SYMTAB_SPACE)
-       /* Save the symbol locations. */
-       movl    MOD_START(%ebx),%esi
-       addl    MOD_LEN(%ebx),%esi
-       movl    %esi,RELOC(esym)
-#endif
-
         /* Clear BSS first so that there are no surprises... */
        xorl    %eax,%eax
        movl    $RELOC(__bss_start),%edi
index 61d289809601da8bfa4166abee865adcb72b9277..5ec2d45271c58a567742578a153f085de9fac6f7 100644 (file)
@@ -2061,7 +2061,6 @@ init386(paddr_t first_avail)
 #if NKSYMS || defined(DDB) || defined(LKM)
        {
                extern int end;
-               extern int *esym;
                struct btinfo_symtab *symtab;
 
 #ifdef DDB
@@ -2077,7 +2076,10 @@ init386(paddr_t first_avail)
                            (int *)symtab->esym);
                }
                else
-                       ksyms_init(*(int *)&end, ((int *)&end) + 1, esym);
+                       ksyms_init(*(int *)&end, ((int *)&end) + 1,
+                                  xen_start_info.mod_start ?
+                                  (void *)xen_start_info.mod_start :
+                                  (void *)xen_start_info.mfn_list);
        }
 #endif
 #ifdef DDB
index bb44e27baca31151ebc129802a35ae59df0ab32f..04e2ac7e4e98170fa2c5fb2edec369e199d02a2d 100644 (file)
 struct domain_setup_info
 {
     unsigned long v_start;
+    unsigned long v_end;
     unsigned long v_kernstart;
     unsigned long v_kernend;
     unsigned long v_kernentry;
 
     unsigned int use_writable_pagetables;
+    unsigned int load_bsd_symtab;
+
+    unsigned long symtab_addr;
+    unsigned long symtab_len;
 };
 
 static int parseelfimage(char *elfbase, 
@@ -29,6 +34,8 @@ static int parseelfimage(char *elfbase,
                          struct domain_setup_info *dsi);
 static int loadelfimage(char *elfbase, void *pmh, unsigned long *parray,
                         unsigned long vstart);
+static int loadelfsymtab(char *elfbase, void *pmh, unsigned long *parray,
+                         struct domain_setup_info *dsi);
 
 static long get_tot_pages(int xc_handle, u32 domid)
 {
@@ -125,6 +132,9 @@ static int setup_guestos(int xc_handle,
         xc_domain_setvmassist(xc_handle, dom, VMASST_CMD_enable,
                               VMASST_TYPE_writable_pagetables);
 
+    if (dsi.load_bsd_symtab)
+        loadelfsymtab(image, NULL, NULL, &dsi);
+
     if ( (dsi.v_start & (PAGE_SIZE-1)) != 0 )
     {
         PERROR("Guest OS must load to a page boundary.\n");
@@ -138,13 +148,13 @@ static int setup_guestos(int xc_handle,
      * read-only). We have a pair of simultaneous equations in two unknowns, 
      * which we solve by exhaustive search.
      */
+    vinitrd_start    = round_pgup(dsi.v_end);
+    vinitrd_end      = vinitrd_start + initrd_len;
+    vphysmap_start   = round_pgup(vinitrd_end);
+    vphysmap_end     = vphysmap_start + (nr_pages * sizeof(unsigned long));
+    vpt_start        = round_pgup(vphysmap_end);
     for ( nr_pt_pages = 2; ; nr_pt_pages++ )
     {
-        vinitrd_start    = round_pgup(dsi.v_kernend);
-        vinitrd_end      = vinitrd_start + initrd_len;
-        vphysmap_start   = round_pgup(vinitrd_end);
-        vphysmap_end     = vphysmap_start + (nr_pages * sizeof(unsigned long));
-        vpt_start        = round_pgup(vphysmap_end);
         vpt_end          = vpt_start + (nr_pt_pages * PAGE_SIZE);
         vstartinfo_start = vpt_end;
         vstartinfo_end   = vstartinfo_start + PAGE_SIZE;
@@ -200,6 +210,9 @@ static int setup_guestos(int xc_handle,
 
     loadelfimage(image, pm_handle, page_array, dsi.v_start);
 
+    if (dsi.load_bsd_symtab)
+        loadelfsymtab(image, pm_handle, page_array, &dsi);
+
     /* Load the initial ramdisk image. */
     if ( initrd_len != 0 )
     {
@@ -656,10 +669,15 @@ static int parseelfimage(char *elfbase,
     if ( (p = strstr(guestinfo, "PT_MODE_WRITABLE")) != NULL )
         dsi->use_writable_pagetables = 1;
 
+    if ( (p = strstr(guestinfo, "BSD_SYMTAB")) != NULL )
+        dsi->load_bsd_symtab = 1;
+
     dsi->v_kernstart = kernstart;
     dsi->v_kernend   = kernend;
     dsi->v_kernentry = ehdr->e_entry;
 
+    dsi->v_end       = dsi->v_kernend;
+
     return 0;
 }
 
@@ -706,3 +724,114 @@ static int loadelfimage(char *elfbase, void *pmh, unsigned long *parray,
     return 0;
 }
 
+static void map_memcpy(unsigned long dst, char *src, unsigned long size,
+                       void *pmh, unsigned long *parray, unsigned long vstart)
+{
+    char *va;
+    unsigned long chunksz, done, pa;
+
+    for ( done = 0; done < size; done += chunksz )
+    {
+        pa = dst + done - vstart;
+        va = map_pfn_writeable(pmh, parray[pa>>PAGE_SHIFT]);
+        chunksz = size - done;
+        if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) )
+            chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1));
+        memcpy(va + (pa & (PAGE_SIZE-1)), src + done, chunksz);
+        unmap_pfn(pmh, va);
+    }
+}
+
+#define ELFROUND (ELFSIZE / 8)
+
+static int loadelfsymtab(char *elfbase, void *pmh, unsigned long *parray,
+                         struct domain_setup_info *dsi)
+{
+    Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase, *sym_ehdr;
+    Elf_Shdr *shdr;
+    unsigned long maxva, symva;
+    char *p;
+    int h, i;
+
+    p = malloc(sizeof(int) + sizeof(Elf_Ehdr) +
+               ehdr->e_shnum * sizeof(Elf_Shdr));
+    if (p == NULL)
+        return 0;
+
+    maxva = (dsi->v_kernend + ELFROUND - 1) & ~(ELFROUND - 1);
+    symva = maxva;
+    maxva += sizeof(int);
+    dsi->symtab_addr = maxva;
+    dsi->symtab_len = 0;
+    maxva += sizeof(Elf_Ehdr) + ehdr->e_shnum * sizeof(Elf_Shdr);
+    maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
+
+    shdr = (Elf_Shdr *)(p + sizeof(int) + sizeof(Elf_Ehdr));
+    memcpy(shdr, elfbase + ehdr->e_shoff, ehdr->e_shnum * sizeof(Elf_Shdr));
+
+    for ( h = 0; h < ehdr->e_shnum; h++ ) 
+    {
+        if ( shdr[h].sh_type == SHT_STRTAB )
+        {
+            /* Look for a strtab @i linked to symtab @h. */
+            for ( i = 0; i < ehdr->e_shnum; i++ )
+                if ( (shdr[i].sh_type == SHT_SYMTAB) &&
+                     (shdr[i].sh_link == h) )
+                    break;
+            /* Skip symtab @h if we found no corresponding strtab @i. */
+            if ( i == ehdr->e_shnum )
+            {
+                shdr[h].sh_offset = 0;
+                continue;
+            }
+        }
+
+        if ( (shdr[h].sh_type == SHT_STRTAB) ||
+             (shdr[h].sh_type == SHT_SYMTAB) )
+        {
+            if ( pmh != NULL )
+                map_memcpy(maxva, elfbase + shdr[h].sh_offset, shdr[h].sh_size,
+                           pmh, parray, dsi->v_start);
+
+            /* Mangled to be based on ELF header location. */
+            shdr[h].sh_offset = maxva - dsi->symtab_addr;
+
+            dsi->symtab_len += shdr[h].sh_size;
+            maxva += shdr[h].sh_size;
+            maxva = (maxva + ELFROUND - 1) & ~(ELFROUND - 1);
+        }
+
+        shdr[h].sh_name = 0;  /* Name is NULL. */
+    }
+
+    if ( dsi->symtab_len == 0 )
+    {
+        dsi->symtab_addr = 0;
+        goto out;
+    }
+
+    if ( pmh != NULL ) {
+        *(int *)p = maxva - dsi->symtab_addr;
+        sym_ehdr = (Elf_Ehdr *)(p + sizeof(int));
+        memcpy(sym_ehdr, ehdr, sizeof(Elf_Ehdr));
+        sym_ehdr->e_phoff = 0;
+        sym_ehdr->e_shoff = sizeof(Elf_Ehdr);
+        sym_ehdr->e_phentsize = 0;
+        sym_ehdr->e_phnum = 0;
+        sym_ehdr->e_shstrndx = SHN_UNDEF;
+
+        /* Copy total length, crafted ELF header and section header table */
+        map_memcpy(symva, p, sizeof(int) + sizeof(Elf_Ehdr) +
+                   ehdr->e_shnum * sizeof(Elf_Shdr), pmh, parray,
+                   dsi->v_start);
+    }
+
+    dsi->symtab_len = maxva - dsi->symtab_addr;
+    dsi->v_end = round_pgup(maxva);
+
+ out:
+    if ( p != NULL )
+        free(p);
+
+    return 0;
+}